package sicnu.cs.ich.common.services.impl;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.BatchStatus;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import sicnu.cs.ich.api.common.enums.FileEnum;
import sicnu.cs.ich.common.config.CloudStorageConfig;
import sicnu.cs.ich.common.services.IFileUploadService;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * @author 沈洋 邮箱:1845973183@qq.com
 * @create 2021/11/14-15:16
 **/
@Slf4j
@Service
public class QiniuServiceImpl implements IFileUploadService {
    /**
     * 云存储配置
     */
    private final CloudStorageConfig config;
    // 七牛文件上传管理器
    private UploadManager uploadManager;
    private String token;
    private BucketManager bucketManager;

    public QiniuServiceImpl(CloudStorageConfig config) {
        this.config = config;
        init();
    }

    private void init() {
        // 构造一个带指定Zone对象的配置类, 注意这里的Zone.zone0需要根据主机选择
        Configuration configuration = new Configuration(Zone.zone2());
        uploadManager = new UploadManager(configuration);
        // 七牛认证管理
        Auth auth = Auth.create(config.getQiniuAccessKey(), config.getQiniuSecretKey());
        // 根据命名空间生成的上传token
        token = auth.uploadToken(config.getQiniuBucketName());
        bucketManager = new BucketManager(auth, configuration);
    }

    /**
     * 生成唯一文件名
     */
    public static String getRandomImgName(String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            throw new IllegalArgumentException();
        }

        int index = fileName.lastIndexOf(".");
        if (index == -1) {
            throw new IllegalArgumentException("文件名{" + fileName + "}无后缀名");
        }
        // 获取文件后缀
        String suffix = fileName.substring(index);
        // 生成UUID
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        // 生成上传至云服务器的路径
        return uuid + suffix;
    }

    /**
     * 上传文件
     *
     * @param file     文件流
     * @param fileEnum 文件归档类
     * @param fileName 文件名（会拼上UUID）
     * @return
     * @throws IOException
     */

    @Override
    public String uploadFile(FileInputStream file, FileEnum fileEnum, String fileName) throws IOException {
        var newKey = fileEnum.getValue() + getRandomImgName(fileName);
        Response res = uploadManager.put(file, newKey, token, null, null);
        if (!res.isOK()) {
            throw new RuntimeException("上传七牛出错：" + res.toString());
        }
        // 这个returnPath是获得到的外链地址,通过这个地址可以直接打开图片
        return new Gson().fromJson(res.bodyString(), DefaultPutRet.class).key;
    }


    @Async
    @Override
    public void deleteFile(String key) {
        Response response = null;
        try {
            response = bucketManager.delete(config.getQiniuBucketName(), key);
        } catch (QiniuException e) {
            log.error("删除文件错误");
            return;
        }
        // 重试三次
        int retry = 0;
        while (response.needRetry() && retry++ < 3) {
            try {
                response = bucketManager.delete(config.getQiniuBucketName(), key);
            } catch (QiniuException e) {
                log.error("删除文件错误");
                return;
            }
        }
    }

    /**
     * 批量删除文件
     */
    @Override
    @Async
    public void deleteFile(List<String> keys) {
        //单次批量请求的文件数量不得超过1000
        String[] str = new String[keys.size()];
        str = keys.toArray(str);
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        batchOperations.addDeleteOp(config.getQiniuBucketName(), str);
        Response response = null;
        try {
            response = bucketManager.batch(batchOperations);
            BatchStatus[] batchStatusList = new BatchStatus[0];
            batchStatusList = response.jsonToObject(BatchStatus[].class);
        } catch (QiniuException e) {
            log.info("删除失败");
        }
    }
}
